/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sim.helpers.statistics;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author artem
 */
public class Parser {

    private int index;
    private String changingVariable;
    private String properties;
    private String[] sections = {"CC", "NLI", "ACC"};
    private String[] markers = {"-d", "-o", "-*", "-x", "-s", "-+", "-^", "-v", "->", "-<", "-p", "-h\'\'"};

    public Parser(String properties) {
        this.properties = properties;
    }

    public void parseSingle() {
        String defaultDirectory = System.getProperty("user.home") + "/Desktop/";
        File f1 = new File(defaultDirectory);
        FilenameFilter only = new OnlyExt("msr");
        String s[] = f1.list(only);
        for (int i = 0; i < s.length; i++) {
            System.out.println("[I] Parsing file " + s[i]);
            File mDir = new File(defaultDirectory + s[i].substring(0, (s[i].length() - 4)));
            mDir.mkdir();
            //Create data dir
            File dDir = new File(mDir, "Data");
            dDir.mkdir();
            for (String section : sections) {
                try {
                    File sectionFile = new File(dDir, section + ".m");
                    FileWriter fstream = new FileWriter(sectionFile);
                    BufferedWriter out = new BufferedWriter(fstream);
                    out.write(getSingleSectionValues(new File(defaultDirectory, s[i]), section));
                    out.close();
                } catch (IOException ex) {
                    Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            //Backup initial file
            File tmp = new File(defaultDirectory, s[i]);
            tmp.renameTo(new File(mDir, s[i]));
        }
    }

    private String getSingleSectionValues(File file, String section) {
        FileInputStream fstream = null;
        String ret = "";
        try {
            fstream = new FileInputStream(file);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            boolean flagSectionFound = false;
            while ((strLine = br.readLine()) != null) {
                if (strLine.contains(":")) {
                    if (strLine.contains(section)) {
                        flagSectionFound = true;
                    } else {
                        flagSectionFound = false;
                    }
                } else {
                    if (!flagSectionFound) {
                        continue;
                    } else {
                        if (strLine.contains("NaN")) {
                            strLine = strLine.replace("NaN", "0");
                        }
                        ret += strLine + "\n";
                    }
                }
            }
            in.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                fstream.close();
            } catch (IOException ex) {
                Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return ret;
    }

    public void parseMultiple() {
        try {
            String desktopDirString = System.getProperty("user.home") + "/Desktop/";
            File desktop = new File(desktopDirString);
            File defaultDir = new File(desktop, changingVariable);
            defaultDir.mkdir();
            //Find changing variable for single simulation
            String chVarFromProperties = "";
            Properties config = new Properties();
            config.load(new java.io.FileInputStream(properties));
            chVarFromProperties = config.getProperty("CHANGING_CONSTANT");
            //Done
            FilenameFilter only = new OnlyBeg(chVarFromProperties);
            String singleSimulationDirs[] = desktop.list(only);
            for (String directory : singleSimulationDirs) {
                if (directory.length() < 10) {
                    continue;
                }
                File tmpFile = new File(desktop, directory);
                tmpFile.renameTo(new File(defaultDir, directory));
            }
            for (String section : sections) {
                System.out.print("[I]\tParsing " + section + " simulation files. ");
                File mDataFile = new File(defaultDir, chVarFromProperties + section + "Plot.m");
                Writer out = new OutputStreamWriter(new FileOutputStream(mDataFile));
                out.write(getTotalMFileData(defaultDir, singleSimulationDirs, section));
                out.close();
                System.out.println("Done");
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String getTotalMFileData(File directory, String[] listing, String section) {
        String ret = "clf;\nclc\nclear\nfigure\nhold on;\ngrid on;\n";
        int count = -1;
        String[] variableValue = new String[listing.length];
        for (String subDir : listing) {
            count++;
            if (subDir.length() < 10) {
                continue;
            }
            File singleSimulationDir = new File(directory, subDir);
            OnlyExt only = new OnlyExt("msr");
            String[] overviewS = singleSimulationDir.list(only);
            for (String overview : overviewS) {
                variableValue[count] = getVariableValue(new File(singleSimulationDir, overview));
            }
            ret += ("A" + count + " = importdata(\'" + singleSimulationDir.getName() + "/Data/" + section + ".m\', \'\\t\');\n");
            ret += ("x" + count + " = A" + count + "(:,1);\n");
            ret += ("y" + count + " = A" + count + "(:,2);\n");
        }
        for (int i = 0; i < listing.length; i++) {
            ret += "plot(x" + i + ", y" + i + ", \'" + markers[i] + "\');\n";
            ret += "hold on;\n";
        }
        ret += "xlabel=(\'\');\n";
        ret += "ylabel=(\'\');\n";
        ret += "legend(";
        String variable = "";
        if (changingVariable.equalsIgnoreCase("qos")) {
            variable = "QOS";
        } else if (changingVariable.equalsIgnoreCase("sd")) {
            variable = "\\sigma";
        } else if (changingVariable.equalsIgnoreCase("n")) {
            variable = "N";
        } else if (changingVariable.equalsIgnoreCase("l")) {
            variable = "L";
        } else if (changingVariable.equalsIgnoreCase("Rep")) {
            variable = "Rep.";
        } else {
            variable = "N";
        }
        for (int i = 0; i < listing.length; i++) {
            ret += "\'" + variable + " = " + variableValue[i];
            if (i == listing.length - 1) {
                ret += "\');\n";
            } else {
                ret += "\', ";
            }
        }
        ret += "hold off;";
        return ret;
    }

    private String getVariableValue(File file) {
        FileInputStream fstream = null;
        String ret = "";
        String variable = "";
        try {
            if (changingVariable.equalsIgnoreCase("qos")) {
                variable = "QOS";
            } else if (changingVariable.equalsIgnoreCase("sd")) {
                variable = "SD";
            } else if (changingVariable.equalsIgnoreCase("n")) {
                variable = "N";
            } else if (changingVariable.equalsIgnoreCase("l")) {
                variable = "L";
            } else if (changingVariable.equalsIgnoreCase("Rep")) {
                variable = "H";
            } else {
                variable = "NODES";
            }
            fstream = new FileInputStream(file);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            while ((strLine = br.readLine()) != null) {
                if (strLine.contains(variable)) {
                    String[] values = strLine.split("\\s+");
                    ret = values[1];
                    break;
                } else {
                    continue;
                }
            }
            in.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                fstream.close();
            } catch (IOException ex) {
                Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
            }
            return ret;
        }
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the variable
     */
    public String getVariable() {
        return changingVariable;
    }

    /**
     * @param variable the variable to set
     */
    public void setVariable(String variable) {
        this.changingVariable = variable;
    }

    private class OnlyExt implements FilenameFilter {

        private String ext;

        private OnlyExt(String ext) {
            this.ext = "." + ext;
        }

        @Override
        public boolean accept(File dir, String name) {
            return name.endsWith(ext);
        }
    }

    private class OnlyBeg implements FilenameFilter {

        private String ext;

        private OnlyBeg(String ext) {
            this.ext = ext;
        }

        @Override
        public boolean accept(File dir, String name) {
            return name.startsWith(ext);
        }
    }
}
